<?php
/**
 * 取得语言对应的locale值
 * @param string $language_alias
 * @return string
 */
function getLocal($language_alias) {
    if (!class_exists('I18n')) {
        App::uses('I18n', 'I18n');
    }
    $I18n = I18n::getInstance();
    $I18n->l10n->get($language_alias);
    return $I18n->l10n->locale;
}
$GLOBALS['lang'] = array();

function load_lang($type='default'){
	$pathes = App::path('locales');
	$language = Configure::read('Site.language');
	$locale = getLocal($language);
	foreach($pathes as $path){
		$file = $path.DS.$locale.DS.$type.'.php';
		if(!defined('LANGUAGE_'.strtoupper($type)) && file_exists($file)){
			$tmp = include_once $file;
			$GLOBALS['lang'] = array_merge($GLOBALS['lang'],$tmp);
		}
	}
}

function is_phone_number($mobile) {
	$mobile = preg_replace('/-\s/','',$mobile);
	if(is_numeric($mobile) && strlen($mobile) ==11){ //11位数字
			return true;
	}
	elseif(strpos($mobile,'+') !== false){
		return true;
	}
	else{
		
	}
	return false;
}

function lang($name){
	if(isset($GLOBALS['lang'][$name])){
		return $GLOBALS['lang'][$name];
	}
	else{	
		return Inflector::humanize($name);
	}
}

/**
 * 将Configure配置项，写入到配置文件中. 主要是settings表中的记录
 * 仅在settings文件不存在时执行一次
 * 
 * Configure::dump($key, $config = 'default', $keys = array())
 */
function write_configure_setting(){
	/**
	 * 将不用写入到settings表中的项清除，防止在配置app/Config/core.php修改内容时，不生效。表dump文件的项覆盖
	 */
	$tmp = Configure::delete('debug');
	$tmp_app = Configure::delete('App');
	$tmp_cache = Configure::delete('Cache');
	$tmp_error = Configure::delete('Error');
	$tmp_exception = Configure::delete('Exception');
	$tmp_session = Configure::delete('Session');
	$tmp_acl = Configure::delete('Acl');
	$tmp_dispatcher = Configure::delete('Dispatcher');
	$tmp_install = Configure::delete('Install');


	Configure::dump('settings','default');// ,array('Hook','Security')

	// 删除不必要保存到缓存配置文件的设置项，在保存到文件后，恢复值
	Configure::write('debug',$tmp);
	Configure::write('App',$tmp_app);
	Configure::write('Cache',$tmp_cache);
	Configure::write('Error',$tmp_error);
	Configure::write('Exception',$tmp_exception);
	Configure::write('Session',$tmp_session);
	Configure::write('Acl',$tmp_acl);
	Configure::write('Dispatcher',$tmp_dispatcher);
	Configure::write('Install',$tmp_install);
}

function clearCoreModelCache(){
	Cache::clear(false, '_cake_model_');
	Cache::clear(false, '_cake_core_');
}
/**
 * 删除所有缓存
 */
function clearCacheAll(){
	//Cache::config('front', array('engine' => 'File', 'prefix' => 'ideacms_app_',));
	//Cache::clear(false, 'front');
// 	clearFolder(WEB_VISIT_CACHE);
	clearFolder(DATA_PATH.DS.'cache'.DS.'views',true);
	clearFolder(DATA_PATH.DS.'cache',false);
	Cache::clear(false, '_cake_model_');
	Cache::clear(false, '_cake_core_');
	Cache::clear(false, 'default');
	//@unlink(DATA_PATH.DS.'settings.php');
}
/**
 * 清空文件夹下的所有文件
 * @param string $dir 文件夹路径
 * @param boolean $recusive 是否递归删除目录
 * @return boolean
 */
function clearFolder($dir,$recusive=false){
	if (is_dir($dir)) {
		$files = glob($dir .DS. '*');
		if ($files === false) {
			return false;
		}
	
		foreach ($files as $file) {
			if(in_array($file,array('.','..'))){
				continue;
			}
			elseif (is_file($file)) {
				@unlink($file);
			}
			elseif($recusive && is_dir($file)){
				clearFolder($file,$recusive);
				// 不删除文件夹，保留目录下所有文件夹。如删除缓存时，需要保留现有缓存下的文件夹
				//@rmdir($file);
			}
		}
		return true;
	}
}

function check_permission($aco) {
	
	$user = CakeSession::read('Auth.User');
	
	if( $user['id']) {
		
		App::uses('AclInterface', 'Controller/Component/Acl');
		$aclAdapter = Configure::read('Acl.classname');
		App::uses( $aclAdapter, 'Controller/Component/Acl');
		$acl = new $aclAdapter();
		
		$role_ids = array();
		$role_ids[] = 2; //普通注册组
		if(is_array($user['Role'])) {
			foreach($user['Role'] as $role) {
				$role_ids[] = $role['id'];
			}
		}
		if( $acl->check(array('model'=>'Role','foreign_key'=>$role_ids),$aco) ){
			return 1;
		}
	}
	return 0;
	
}

function is_valid_url($url){
    $heads = get_headers($url);
    if( is_array($heads) && preg_match('/200/',$heads[0]) ){
        return true;
    }else{
        return false;
    }
}


function is_image($url){
	$file_type = get_mime_type($url);
	if(in_array($file_type,array ("image/png", "image/gif", "image/jpeg", "image/bmp", "image/jpg"))){
		return true;
	}
	return false;
}
/**
 * 是否为搜索引擎抓取
 * @param string $user_agent
 * @return boolean
 */
function is_search_bot($user_agent) {
    if (preg_match('/(bot|spider|baidu|google)/is', $user_agent, $matches)) {
//		print_r($matches);
        return true;
    }
    else
        return false;
}
/**
 * 加载获取一个Model对象，如果不存在时返回false
 * @param string $modelClass
 * @param string $plugin
 * @return boolean|Ambigous <mixed, boolean, multitype:>|Ambigous <mixed, boolean, multitype:, object, unknown>
 */
function loadModelObject($modelClass,$plugin='') {
	if(empty($modelClass)){
		return false;
	}
    $model = false;
    if ($model = ClassRegistry::getObject($modelClass)) {
        return $model;
    }
    else{
//$plugin .,加上plugin时，购物淘宝客页面显示错误，会莫名其妙的调用setting，暂未发现原因
    	$model =  ClassRegistry::init(array(
    			'class' =>  $modelClass, 'alias' => $modelClass, 'id' => null
    	));
    	ClassRegistry::addObject($plugin . $modelClass, $model);
    	return $model;
    }
}

/**
 * 获取exception的全量stack strace错误输出。$e->getTraceAsString()；默认的被截取字符串，显示不完整
 * @param Exception $exception
 * @return string
 */
function getExceptionTraceAsString($exception) {
    $rtn = "";
    $count = 0;
    foreach ($exception->getTrace() as $frame) {
        empty($frame['file']) && $frame['file'] = "[internal function]";
        empty($frame['class']) || $frame['class'] = $frame['class']."->";
        $args = "";
        if (isset($frame['args'])) {
            $args = array();
            foreach ($frame['args'] as $arg) {
                if (is_string($arg)) {
                    $args[] = "'" . $arg . "'";
                } elseif (is_array($arg)) {
                    $args[] = "Array";
                } elseif (is_null($arg)) {
                    $args[] = 'NULL';
                } elseif (is_bool($arg)) {
                    $args[] = ($arg) ? "true" : "false";
                } elseif (is_object($arg)) {
                    $args[] = get_class($arg);
                } elseif (is_resource($arg)) {
                    $args[] = get_resource_type($arg);
                } else {
                    $args[] = $arg;
                }
            }
            $args = join(", ", $args);
        }
        $rtn .= sprintf( "#%s %s(%s): %s%s(%s)\n",
            $count,
            $frame['file'],
            $frame['line'],
            $frame['class'],
            $frame['function'],
            $args );
        $count++;
    }
    return $rtn;
}

function send_msg($mobile,$msg){
	App::uses('Yunpian', 'Lib');
	$sms_appkey = Configure::read('User.sms_key');
	if( $sms_appkey ) {
	    Yunpian::$apikey = $sms_appkey;
	}
    		
	$result = Yunpian::single_send($mobile,$msg);
		
	if(isset($result['code']) && $result['code']==0 ) {
	    return array('ret'=> 0,'msg'=>'短信已发送，请注意查收');
	}
	else{
		CakeLog::error("send_msg yunpian:{$mobile}:{$msg}\nerror:".var_export($result,true));
		return array('ret'=> -1, 'msg'=> '短信发送失败，原因为：'.$result['msg'].'。'.$result['detail']);    		
	}
}

function get_short_url($url){
	App::uses('WeiboUtility', 'Utility');
	return WeiboUtility::sinaShortenUrl($url);
}

/**
 * 判断模块对应的数据表是否存在
 * @param unknown_type $modelClass
 * @param unknown_type $plugin
 * @return boolean
 */
function ModelExists($modelClass,$plugin=''){
	if(empty($modelClass)){
		return false;
	}
	try{
		$model = loadModelObject($modelClass,$plugin);
		// $model->getDataSource(); //getDataSource调用获取表格信息，判断表格是否存在。
		$model->schema(); 
	}
	catch(MissingTableException $e){
		return false;
	}
	catch(Exception $e){
		return false;
	}
	return true;
}

/**
 * 用于安装时，导入tree结构的模块数据。让id不固定，并能保存上下级关系。
 * @param array $datas	数据
 * @param string $modelname	模型名称
 * @param int $parentid	上级分类
 */
function saveTreeItems($datas,$modelname,$parentid=null,&$model = null){
	if(empty($model)){
		$model = loadModelObject($modelname);
		$model->recursive = -1;
		if($model->Behaviors->enabled('Tree')){
			$model->Behaviors->disable('Tree'); // 设置了id值tree数据无法插入，先取消tree行为插入数据，再绑定tree行为修复数据。
		}
// 		$model->useDbConfig = 'master';
// 		$model->Behaviors->load('Tree', array('left'=>'left','right'=>'right'));
	}
	$fields = array_keys($model->schema());
	foreach($datas as $item){
// 		$tmpid = $item[$modelname]['id'];
// 		$item[$modelname]['id'] = null; // tree根据id来查询节点。需要先替换id为空，插入后再设置回id的值。
		if(in_array('model',$fields) && !empty($item[$modelname]['model']) && !ModelExists($item[$modelname]['model'])){
			continue;//含model，且对应模块不存在（未安装对应模块）的跳过。如栏目对应的模块
		}
// 		if($parentid){
// 			$item[$modelname]['parent_id'] = $parentid;
// 		}
		$model->create();
		$model->save($item);
		$inner_parentid = $model->id ? $model->id : $model->getLastInsertID();
		
// 		$model->updateAll(array('id'=>$tmpid),array('id'=>$insertid));
// 		$inner_parentid = $tmpid;
		if(!empty($item['children'])){ // $inner_parentid && 
			saveTreeItems($item['children'],$modelname,$inner_parentid,$model);
		}
	} // 按数据的parent_id导入，导入完成后，在fix左右节点
	if($parentid==null){ // 最外层的函数
		// aro,aco等树结构左右节点为lft,rght.
		if(in_array('lft',$fields) && in_array('rght',$fields)){
			$model->Behaviors->load('Tree', array('left'=>'lft','right'=>'rght'));
		}
		else{
			$model->Behaviors->load('Tree', array('left'=>'left','right'=>'right'));
		}
		$model->recover('parent');
	}
}

/**
 * SimpleHtmlDom 的$stripRN要设为false，去掉换行符后，所有内容变成一行，css、js等会出现错误。
 */
// helper functions
// -----------------------------------------------------------------------------
// get html dom from file
// $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1.
function file_get_html($url, $use_include_path = false, $context=null, $offset = -1, $maxLen=-1, $lowercase = true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=false, $defaultBRText=DEFAULT_BR_TEXT)
{
	App::uses('SimpleHtmlDom', 'Utility');
    // We DO force the tags to be terminated.
    $dom = new SimpleHtmlDom(null, $lowercase, $forceTagsClosed, $target_charset, $defaultBRText);
    // For sourceforge users: uncomment the next line and comment the retreive_url_contents line 2 lines down if it is not already done.
    $contents = file_get_contents($url, $use_include_path, $context, $offset);
    // Paperg - use our own mechanism for getting the contents as we want to control the timeout.
//    $contents = retrieve_url_contents($url);
    if (empty($contents))
    {
        return false;
    }
    // The second parameter can force the selectors to all be lowercase.
    $dom->load($contents, $lowercase, $stripRN);
    return $dom;
}

// get html dom from string
function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=false, $defaultBRText=DEFAULT_BR_TEXT)
{
	if (empty($str)){
		return false;
	}
	App::uses('SimpleHtmlDom', 'Utility');
    $dom = new SimpleHtmlDom(null, $lowercase, $forceTagsClosed, $target_charset, $defaultBRText);
    $dom->load($str, $lowercase, $stripRN);
    return $dom;
}

// dump html dom tree
function dump_html_tree($node, $show_attr=true, $deep=0)
{
    $node->dump($node);
}


function liteContent($content) {
    require_once ROOT.DS.'lib/Vendor/DiDom/Document.php';
    
    $content = strip_tags($content,'<p><br><span><fieldset><strong><img><sup><sub><section><hr><table><thead><tbody><tr><td><th>');

    /*去除font-family的字体设置。 */
    $content = str_replace('&quot;','{=quot=}',$content);
    $content = preg_replace('/font-family\s*:\s*[^"]+?;/is','',$content);//已分号间隔的。
    $content = preg_replace('/font-family\s*:\s*[^"]+?("|\')/is',"\\1",$content); //在最后无分号，直接带引号的
    $content = str_replace('{=quot=}','&quot;',$content);
    
    //去掉style中的引号。字体，背景图路径
    $content = str_replace('&quot;','',$content);
    
    return $content;
}


function parseFragContent($content,$frag,&$i) {
    if(empty($frag)) return $content;
    require_once ROOT.DS.'lib/Vendor/DiDom/Document.php';
    
    $dom =  new DiDom\Document($content);
//     $dom = str_get_html($content);
    $brush = $dom->find('.135brush');
    
    if(count($brush) == 1 ){
//         echo  $content = $dom->outertext; return $content;
//         return $content = $dom->html();
        $skip = $brush[0]->getAttribute('data-autoskip');
        if($brush[0]->getAttribute('data-brushtype')!='text' && empty($skip) ) {
            $style = $brush[0]->getAttribute('data-style');
            if( $style  ) { //
                if(strpos($style,'width') === false) { // 无设置宽度，不为竖向的内容
                    //$brush[0]->setAttribute('innertext','<p style="'.$brush[0]->getAttribute('data-style').'">'.nl2br($frag['Frag']['summary']).'</p>');
                	$brush[0]->setValue("");
                	
                	$doc = $dom->getDocument();
                    $lines = explode("\r\n",trim($frag['Frag']['summary']));
                    foreach($lines as $k => $line) {
                    	if($k > 0) {
                    		$node = $doc->createElement("br");
                    		$brush[0]->appendChild($node);
                    	}
                    	$node = $doc->createElement("p");
                    	$node->setAttribute("style", $brush[0]->getAttribute('data-style'));
                    	$node->nodeValue = $line;
                    	//$node->nodeValue = ( nl2br($frag['Frag']['summary']) );
                    	$brush[0]->appendChild($node);
                    }
                    //$brush[0]->setValue('<p style="'.$brush[0]->getAttribute('data-style').'">'.nl2br($frag['Frag']['summary']).'</p>');
                    $i++;
                }
            }
            else{
                $doc = $dom->getDocument();
                $brush[0]->setValue("");
                
                $lines = explode("\r\n",trim($frag['Frag']['summary']));
                foreach($lines as $k => $line) {
                	if($k > 0) {
                		$node = $doc->createElement("br");
                		$brush[0]->appendChild($node);
                	}
                	$node = $doc->createElement("p");
                	$node->nodeValue = $line;
                	//$node->nodeValue = ( nl2br($frag['Frag']['summary']) );
                	$brush[0]->appendChild($node);
                }
                
                //$brush[0]->innertext='<p>'.nl2br($frag['Frag']['summary']).'</p>';
                //$brush[0]->setValue('<p>'.nl2br($frag['Frag']['summary']).'</p>');$
                $i++;
            }
//             $content = $dom->outertext;
            $content = $dom->html();
            unset($brush,$dom);
        }
    }
    return $content;
}




function getStaticFileUrl($url,$full=true){
	$url = Router::url($url,$full);
	$url = str_replace(env('SCRIPT_NAME'),'',$url);
	return $url;
}


/**
 * close all open xhtml tags at the end of the string
 * @param string $html
 * @return string
 */
function closetags($html) {
	#put all opened tags into an array
	preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
	$openedtags = $result[1];
	#put all closed tags into an array
	preg_match_all('#</([a-z]+)>#iU', $html, $result);
	$closedtags = $result[1];
	$len_opened = count($openedtags);
	# all tags are closed
	if (count($closedtags) == $len_opened) {
		return $html;
	}
	$openedtags = array_reverse($openedtags);
	# close tags
	for ($i=0; $i < $len_opened; $i++) {
		if (!in_array($openedtags[$i], $closedtags)){
			$html .= '</'.$openedtags[$i].'>';
		}
		else {
			unset($closedtags[array_search($openedtags[$i], $closedtags)]);
		}
	}
	return $html;
}
/**
 * 获取分页显示的链接
 * @param $total
 * @param $request
 * @param $current_page
 */
function getPageLinks($total, $pagesize, $url, $current_page=1,$page_name='page',$page_num = 7) {
    App::uses('Page', 'Lib');
    if($url instanceof CakeRequest){
	    $url_array = array(
	        'controller' => $url->params['controller'],
	        'action' => $url->params['action'],
	        'plugin' => $url->params['plugin'],
	    );
	    $url_array = array_merge($url_array, $url->params['pass'], $url->params['named']);
	    $url_array = array_rawurlencode($url_array);
	    $query = $url->query;
	    unset($url_array[$page_name]);
	    
	    
	    /*将request对象转变了url字符串*/
	    $url = Router::url($url_array);
    }
    else{ // url is array or string
    	$url = Router::url($url);
    	$query = $_GET;
    }
    unset($query[$page_name],$query['_']);//"_" is append by jquery ajax.
    if (!empty($query)) {
        $querystring = http_build_query($query);
        
//         foreach ($query as $key => $val) {
//             $querystring .= $key . '=' . urlencode($val) . '&';
//         }
//         $querystring = htmlspecialchars(substr($querystring, 0, -1));
        $url = $url . '?' . $querystring;
    }
    $pagelinks = new Page($total, $pagesize, $url, $current_page);
    $pagelinks->setPageName($page_name);
    return $page_navi = $pagelinks->renderNav($page_num);
}

/**
 * 获取搜索的条件
 * @param array() $query query参数与值，
 * @param string $modelClass 查询的模块
 * @param boolean $isjoin 是否是连接查询的条件，连接查询条件必须以$modelClass.开头
 */
function getSearchOptions($query,$modelClass){
	/**
	 * 当包含get参数时，当参数名与数据表的字段名相同时，将此get参数加入搜索条件
	 */
	$conditions = array();
	$object = loadModelObject($modelClass);
	//$fileds = $object->getExtSchema();
	$fileds = $object->schema();
	$filedkeys = array_keys($fileds);
//	if(in_array('published',$filedkeys)){
//		$conditions[$modelClass.'.published'] = 1;
//	}
// 	if(in_array('deleted',$filedkeys)){ // 在删除到回收站时，将published置0，只需要判断published一个条件即可
// 		$conditions[$modelClass.'.deleted'] = 0;
// 	}
	
	if(!empty($query)){
// 		foreach($fileds as $fn => $fi){
// 			if(!empty($query[$fn])){
// 				if($fi['associatetype'] == 'treenode' && !empty($fi['selectmodel'])){
// 					$selectmodel = loadModelObject($fi['selectmodel']);
// 					$selectmodel->recursive = -1;
// 					if($selectmodel->actsAs['Tree']){
// 						if($fi['selectvaluefield']=='id'){
// 							$linkid = $query[$fn];
// 						}
// 						else{
// 							$tmp = $selectmodel->find('first',array('conditions'=>array($fi['selectvaluefield']=> $query[$fn])));
// 							$linkid=$tmp[$fi['selectmodel']]['id'];
// 						}
// 						$children = $selectmodel->children($linkid);
// 						$values = array($query[$fn]);
// 						foreach($children as $item){
// 							$values[] = $item[$fi['selectmodel']][$fi['selectvaluefield']];
// 						}
// 						$conditions[$modelClass.'.'.$fn] = $values;
// 					}
// 				}
// 				if(!isset($conditions[$modelClass.'.'.$fn])){
// 					$conditions[$modelClass.'.'.$fn] = $query[$fn];
// 				}
// 			}
// 		}
		
		foreach ($query as $key => $val) {
		    if($key == 'conditions') {
		        continue;
		    }
			if(strpos($key,$modelClass.'_')===0){ // Article.name=xxx 的get参数，变成了Article_name.xxx  转换回去。
				$key = str_replace($modelClass.'_', $modelClass.'.', $key);
			}
			preg_match('/^([\w\.]+)/',$key, $matches);// 形如field_name
			// print_r($matches);
			//strpos($key, $jv['alias'] . '.' . $mk) === 0
			if(in_array($matches[1],$filedkeys)){ // 字符部分为字段名时
				if($key!=$matches[1]){ //不等于时追加一个空格，如"price>%3D=100"  -> "price >=100"
					$fieldname = $matches[1];
					$key = $fieldname.' '.substr($key,strlen($fieldname));
					
					$key = $modelClass.'.'.$key;
					
					if ( !in_array($fieldname,array('model')) && in_array($fileds[$fieldname]['type'], array('string', 'text')) ) { // 文本字段加上like作模糊搜索
					    
						if (strpos($key, ' like') !== false) {
							$conditions[$key] = '%' . $val . '%';
						} else {
							$conditions[$key . ' like'] = '%' . $val . '%';
						}
					}
					else{
						$conditions[$key] = $val;
					}
// 					else {
// 						//$this->_extschema
// 						if (in_array($fileds[$fieldname]['selectmodel'],array('Misccate','Modelcate','Category'))){ // 字段值为tree结构（全用Misccate模块）时，加载所有子类id数据
// 							$misccate = ClassRegistry::init(array('class' => $fileds[$fieldname]['selectmodel'], 'alias' => $fileds[$fieldname]['selectmodel'], 'id' => $val));
// 							$chilrens = $misccate->children($val,false,'id');
// 							$ids = array($val);
// 							foreach($chilrens as $child){
// 								$ids[] = $child[$fileds[$fieldname]['selectmodel']]['id'];
// 							}
// 							$conditions[$key] = $ids;
// 						}
// 						else{
// 							$conditions[$key] = $val;
// 						}
// 					}
				}
				else{
					$key = $fieldname = $matches[1];
					if ( !in_array($fieldname,array('model')) && in_array($fileds[$fieldname]['type'], array('string', 'text','content'))) { // 文本字段加上like作模糊搜索
						if (strpos($key, ' like') !== false) {
							$conditions[$modelClass.'.'.$key] = '%' . $val . '%';
						} else {
							$conditions[$modelClass.'.'.$key . ' like'] = '%' . $val . '%';
						}
					}
					else{
						$conditions[$modelClass.'.'.$key] = $val;
					}
				}
			}
		}
	}
	// print_r($conditions);
	return $conditions;
}
/**
 * 获取搜索的链接 . 若传入的链接是CakeRequest对象，返回的链接可以直接使用。
 * 若传入的链接是一个字符串如 /product/view/1，在外部需要router::url()或者Html->url进行再次处理
 * @param mix $request string or request object.页面request对象
 * @param array $extra	搜索追加参数
 * @param array $delparams	需要删除的参数。 （需要减去的参数（如去掉搜索条件），或可能包含<,>,like等；不方便直接数组覆盖，需要手动指定删除的参数字段名）
 * @param boolean $strip_base 是否去除二级目录的信息，去除时 返回结果仍需要调用Router::url($result).在SectionHelper中使用到
 */
function getSearchLinks($url, $extra=array(), $delparams=array(),$strip_base=false) {
	if($url instanceof CakeRequest ){
		$query = $url->query;
		$url = $url->here;
		// $url = $url->base.'/'.$url->url;
		if(empty($query)) $query = array();
	}
	else{
		$query = $_GET;
	}
// 	print_r($url);
	// 删除需要删除的字段查询条件
    foreach ($query as $key => $val) {
        foreach ($delparams as $del) {
           if (strpos($key, $del) === 0) {
               unset($query[$key]);
           }
        }
    }
    // 删除要删除的项后，再合并$extra，防止$extra中的项被删除
    $query = array_delete_value($query ,''); //删除空的参数
    $query = array_merge($query,$extra);

//     $query = array_rawurlencode($query);
    unset($query['page']);  // 去除分页页码参数，搜索的条件全部默认是显示第一页。这里不需要传页码参数，仅翻页链接需要页码参数。
//     $url = Router::url($url_array);
	
    if($strip_base && defined('APP_SUB_DIR')){
    	$url = str_replace(APP_SUB_DIR,'',$url); // 当应用放在二级目录时，替换掉链接的二级目录，在页面显示时，仍需要调用router::url.防止重复
    }
//     if(defined('APPEND_LOCALE_BASE')){
//     	$url = '/..'.$url;
//     }
    if (!empty($query)) {
        $querystring = http_build_query($query);
//         foreach ($query as $key => $val) {
//         	if(!empty($val)){
//             	$querystring .= urlencode($key). '=' . urlencode($val) . '&';
//         	}
//         }
//         $querystring = substr($querystring, 0, -1);        
        $url = $url . '?' . $querystring;
    }
    return $url;
}

/**
 * 生成随机的串
 * @param int $length
 * @param string $type
 */
function random_str($length, $type = "char") {
    if($type == 'num') {
        $chars = "0123456789";
    }
    elseif($type == 'upper') {
        $chars = "ABCDEFGHJKMNPQRSTUVWXYZ";//去除了I,L,O
    }
    elseif($type == 'lower') {
        $chars = "abcdefghjkmnpqrstuvwxyz";//去除了i,l,o
    }
    elseif($type == 'uppernum') {
        $chars = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";//去除了I,L,0,O,1
    }
    elseif($type == 'lowernum') {
        $chars = "abcdefghjkmnpqrstuvwxyz23456789"; //去除了i,1，L,0,o
    }
    else{
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ23456789abcdefghjkmnpqrstuvwxyz";
    }
    //$chars = ($type != 'num') ? "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz" : "123456789";
    $max = strlen($chars) - 1;
    mt_srand((double) microtime() * 1000000);
    $string = '';
    for ($i = 0; $i < $length; $i++) {
        $s = $chars[mt_rand(0, $max)];
        while($i==0 && $type=='num' && $s == '0') { // 数字形式第一个字符的开始为0时，重新生成第一个字符
            $s = $chars[mt_rand(0, $max)];
        }
        $string .= $s;
    }
    return $string;
}
/**
 * 文件大小格式化
 * @param unknown_type $filesize
 * @return string
 */
function format_filesize($filesize){
	if($filesize>1024*1024){
		return round($filesize/(1024*1024),2).'M';
	}
	elseif($filesize>1024){
		return round($filesize/1024,2).'KB';
	}
	else{
		return $filesize.'B';
	}
}

/**
 * 时间格式化
 * @param int $interval 时间间隔
 * @return string
 */
function format_time($interval){
    $str = '';
    /*if($interval>86400){
        $day = floor($interval/86400);
        $str .= $day.'天';
        $interval = $interval - $day*86400;
    }*/
    if($interval >= 3600){
        $hour = floor($interval/3600);
        $str .= ($hour<10?'0':'').$hour.':';
        $interval = $interval-$hour*3600;
    }
    else{
        $str .= '00:';
    }
    if($interval >= 60){
        $min = floor($interval/60);
        $str .= ($min<10?'0':'').$min.':';
        $interval = $interval%60;
    }
    else{
        $str .= '00:';
    }
    if( $interval > 0) {
        $str .= ($interval<10?'0':'').$interval;
    }
    else{
            $str .= '00';
    }
    return $str;
}
/**
 * 时间间隔格式化，时间间隔。几月前，几天前，几时前
 * @param int $interval 时间间隔
 * @return string
 */
function format_time_interval_ago($interval){
    $str = '';
    if($interval >= 2592000){
        $month = floor($interval/2592000);
        $str .= $month.'月';
        $interval = $interval - $month*2592000;
    }
    elseif($interval >= 86400){
        $day = floor($interval/86400);
        $str .= $day.'天';
        $interval = $interval - $day*86400;
    }
    elseif($interval >= 3600){
        $hour = floor($interval/3600);
        $str .= $hour.'时';
        $interval = $interval-$hour*3600;
    }
    elseif($interval >= 60){
        $min = floor($interval/60);
        $str .= $min.'分';
        $interval = $interval%60;
    }
    elseif( $interval ) { //mb_strlen($str)<4 &&
        $str .= $interval.'秒';
    }
    return $str.'前';
}
/**
 * 时间间隔格式化,倒计时，几天几时几分几秒
 * @param int $interval 时间间隔
 * @return string
 */
function format_time_interval($interval){
    $str = '';
    if($interval >= 2592000){
        $month = floor($interval/2592000);
        $str .= $month.'月';
        $interval = $interval - $month*2592000;
    }
    if($interval >= 86400){
        $day = floor($interval/86400);
        $str .= $day.'天';
        $interval = $interval - $day*86400;
    }
    if($interval >= 3600){
        $hour = floor($interval/3600);
        $str .= $hour.'时';
        $interval = $interval-$hour*3600;
    }
    if($interval >= 60){
        $min = floor($interval/60);
        $str .= $min.'分';
        $interval = $interval%60;
    }
    if( $interval ) { //mb_strlen($str)<4 &&
        $str .= $interval.'秒';
    }
    return $str;
}

function format_price($price){
	$intval = explode('.',$price);
	$dot = '';
	$int = $intval[0];
	if(count($intval) == 2) {
		$dot = $intval[1];
	}
	$newval = '';
	$len = strlen($int);
	$mod = ($len-1)%3;
	for($i=0;$i<$len;$i++){
		$newval .= $int[$i];
		if($i%3 == $mod && $i!=$len-1){
			$newval .= ',';
		}
	}
	if($dot){
		return $GLOBALS['currency'][Configure::read('default_currency')].$newval.'.'.$dot;
	}
	else{
		return $GLOBALS['currency'][Configure::read('default_currency')].$newval.'.00';
	}
}

function get_item_allprice($model,$price,$num){
	if($model == 'Role') {
		return $price * intval($num/12)* 10 + $price * ($num%12);
	}
	else{
		return $price*$num;
	}
}

function user_calculate_example($arg1, $arg2) {
    if ($arg1 > $arg2) {
        return 'No';
    } else {
        return 'Yes';
    }
}

/**
 *  根据PHP各种类型变量生成唯一标识号
 * @param mix $mix
 * @return string
 */
function guid_string($mix) {
    if (is_object($mix) && function_exists('spl_object_hash')) {
        return spl_object_hash($mix);
    } elseif (is_resource($mix)) {
        $mix = get_resource_type($mix) . strval($mix);
    } else {
        $mix = serialize($mix);
    }
    return md5($mix);
}

/**
 * 选项转换为数组
 * 0=>女
  1=>男
  2=>不详
 *
 */
function optionstr_to_array($string) {
    $return_array = array();
    $string = str_replace("\r\n","\n",$string);
    $array = explode("\n", $string);
    foreach ($array as $val) {
        if (empty($val)) {
            continue;
        }
        $temp = explode('=>', $val);
        if (count($temp) == 2) {
            $return_array[$temp[0]] = $temp[1];
        } else {
            $return_array[$temp[0]] = $temp[0];
        }
    }
    return $return_array;
}

function resetWechatContent($content) {
	$new_content = preg_replace_callback('~<img\s.*?src=["|\'](http[s]?://.+?)["|\']~is','resetWechatCallback',$content);
	$new_content = preg_replace_callback('~<image\s.*?xlink:href=["|\'](http[s]?://.+?)["|\']~is','resetWechatCallback',$new_content);
	$new_content = preg_replace_callback('~\(["|\']?(http[s]?://.+?)["|\']?\)~is','resetWechatCallback',$new_content);
	$new_content = preg_replace_callback('~&quot;(http[s]?://.+?)&quot;~is','resetWechatCallback',$new_content);
	return $new_content;
}

function resetWechatCallback($matches){
	return str_replace($matches[1],resetWechatUrl($matches[1]), $matches[0]);
}

function resetWechatUrl($srcurl)
{
    $urlinfo = parse_url($srcurl);
    if (substr($urlinfo['path'], 0, 14) == '/cache/remote/') {
        $url = substr($urlinfo['path'], 14);
        @list($url, $rule) = explode('@', $url);
        $url = base64_decode($url);
        if ($url && (strpos($url, 'mmbiz') !== false || strpos($url, 'mmsns') !== false)) { // mmbiz.qlogo.cn
            $url = str_replace('http://mmbiz.qpic.cn', 'https://mmbiz.qlogo.cn', $url);
            $url = str_replace('?wx_fmt=', '.', $url);
            return $url;
        }
    }
    return $srcurl;
}

/**
 * 将xml内容转换成sql查询的选项
 * @param unknown_type $xml
 * @return Ambigous <multitype:, multitype:NULL string >
 */
function parseXmlToSqlOption($xml) {

	$xmlarray = xml_to_array($xml);      //$regioninfo['Region']['conditions']
	$searchoptions = $xmlarray['options'];

	//if (!empty($searchoptions['withsubcategory']) && !empty($this->params['withsubcategory'])) {
	//	$searchoptions = array_merge_recursive($this->params['withsubcategory'], $searchoptions);
		//	    		print_r($searchoptions);
	//}

	$regCondition = array();
	if (!is_array($searchoptions['conditions']['conditionskey'])) {
		$searchoptions['conditions']['conditionskey'] = array($searchoptions['conditions']['conditionskey']);
		$searchoptions['conditions']['conditionsval'] = array($searchoptions['conditions']['conditionsval']);
		$searchoptions['conditions']['valid'] = array($searchoptions['conditions']['valid']);
	}
	if (is_array($searchoptions['conditions']['conditionskey'])) {
		foreach ($searchoptions['conditions']['conditionskey'] as $ck => $value) {
			if ($searchoptions['conditions']['conditionsval'][$ck]) {
				if ($searchoptions['conditions']['valid'][$ck] == 'notempty' && empty($searchoptions['conditions']['conditionsval'][$ck])) {
					continue; //不为空时才成立的条件，取消掉
				}
				if (strpos($value, ' ') === false) {
					/**
					 * 不带空格的conditionskey拼接sql，0 => "conditionskey =conditionsval"
					 * 若为值，需要自己加单引号。主要用于一个表的字段等于另一个的字段,如 a.id = b.aid
					 * @var $joinCondition
					 */
					if(intval($value)==$value){
						$regCondition[] = $searchoptions['conditions']['conditionsval'][$ck];
					}
					else{
						$regCondition[] = $value . ' = ' . $searchoptions['conditions']['conditionsval'][$ck];
					}
				} else {
					/**
					 * 带空格的conditionskey，conditionskey => conditionsval
					 * 支持 >=等操作
					 * @var $joinCondition
					 */
					$regCondition[$value] = $searchoptions['conditions']['conditionsval'][$ck];
				}
			}
		}
	}


	$searchoptions['conditions'] = $regCondition;

	if (!empty($searchoptions['joins'])) {
		$searchoptions['joins'] = array_values($searchoptions['joins']);
		foreach ($searchoptions['joins'] as $jk => $join) {
			$joinCondition = array();
			if (!is_array($join['conditions']['conditionskey'])) {
				$join['conditions']['conditionskey'] = array($join['conditions']['conditionskey']);
				$join['conditions']['conditionsval'] = array($join['conditions']['conditionsval']);
				$join['conditions']['valid'] = array($join['conditions']['valid']);
			}
			if (is_array($join['conditions']['conditionskey'])) {
				foreach ($join['conditions']['conditionskey'] as $ck => $value) {
					if ($join['conditions']['conditionsval'][$ck]) {
						if ($join['conditions']['valid'][$ck] == 'notempty' && empty($join['conditions']['conditionsval'][$ck])) {
							continue; //不为空时才成立的条件，取消掉
						}

						if (strpos($value, ' ') === false) {
							/**
							 * 不带空格的conditionskey拼接sql，0 => "conditionskey =conditionsval"
							 * 若为值，需要自己加单引号。主要用于一个表的字段等于另一个的字段,如 a.id = b.aid
							 * @var $joinCondition
							 */
							if(empty($value) || preg_match('/^\d+$/',$value)){  //为空或数字时，为值
								$joinCondition[] = $join['conditions']['conditionsval'][$ck];
							}
							else{
								$joinCondition[] = $value . ' = ' . $join['conditions']['conditionsval'][$ck];
							}
						} else {
							/**
							 * 带空格的conditionskey，conditionskey => conditionsval
							 * 支持 >=等操作
							 * @var $joinCondition
							 */
							$joinCondition[$value] = $join['conditions']['conditionsval'][$ck];
						}
					}
				}
			}
			if (empty($joinCondition)) {
				unset($searchoptions['joins'][$jk]);
			} else {
				$searchoptions['joins'][$jk]['conditions'] = $joinCondition;
				$searchoptions['joins'][$jk]['table'] = Inflector::tableize($join['table']);
			}
		}
	} else {
		$searchoptions['joins'] = array();
	}
	return $searchoptions;
}

function unicode_decode($name,$charset = 'UTF-8'){//GBK,UTF-8,big5
		$pattern = '/\\\u[\w]{4}/i';
		preg_match_all($pattern, $name, $matches);
		//print_r($matches);exit;
		if (! empty ( $matches )) {
			//$name = '';
			for($j = 0; $j < count ( $matches [0] ); $j ++) {
				$str = $matches [0] [$j];
				if (strpos ( $str, '\u' ) === 0) {
					$code = base_convert ( substr ( $str, 2, 2 ), 16, 10 );
					$code2 = base_convert ( substr ( $str, 4 ), 16, 10 );
					$c = chr ( $code ) . chr ( $code2 );
					if ($charset == 'GBK') {
						$c = iconv ( 'UCS-2BE', 'GBK', $c );
					} elseif ($charset == 'UTF-8') {
						$c = iconv ( 'UCS-2BE', 'UTF-8', $c );
					} elseif ($charset == 'BIG5') {
						$c = iconv ( 'UCS-2BE', 'BIG5', $c );
					} else {
						$c = iconv ( 'UCS-2BE', $charset, $c );
					}
					//$name .= $c;
					$name = str_replace($str,$c,$name);
				}
				//else {
				//	$name .= $str;
				//}
			}
		}
		return $name;
}


function authcode($string, $operation = 'DECODE', $expiry = 7200) {

	$ckey_length = 4;

	$key = md5( Configure::read('Security.salt') );
	$keya = md5(substr($key, 0, 16));
	$keyb = md5(substr($key, 16, 16));
	$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

	$cryptkey = $keya.md5($keya.$keyc);
	$key_length = strlen($cryptkey);

	$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
	$string_length = strlen($string);

	$result = '';
	$box = range(0, 255);

	$rndkey = array();
	for($i = 0; $i <= 255; $i++) {
		$rndkey[$i] = ord($cryptkey[$i % $key_length]);
	}

	for($j = $i = 0; $i < 256; $i++) {
		$j = ($j + $box[$i] + $rndkey[$i]) % 256;
		$tmp = $box[$i];
		$box[$i] = $box[$j];
		$box[$j] = $tmp;
	}

	for($a = $j = $i = 0; $i < $string_length; $i++) {
		$a = ($a + 1) % 256;
		$j = ($j + $box[$a]) % 256;
		$tmp = $box[$a];
		$box[$a] = $box[$j];
		$box[$j] = $tmp;
		$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
	}

	if($operation == 'DECODE') {
		if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
			return substr($result, 26);
		} else {
			return '';
		}
	} else {
		return $keyc.str_replace('=', '', base64_encode($result));
	}

}

/**
 * 将模版中的列表调用参数转换成数组.
 * eval虽然是模板中代码更清晰，但不支持hiphop。另外eval方式不是非常安全，可能加入其它有危害的代码。
 * 故使用parse_str的方式，按url get方式传入字符串。
 * 
 * 例如：
 * 
 * model=Product|cached=900|pagelink=no|title=最新排行|options['fields']=array('Product.id','Product.name','Product.created')|portlet=default|list_tpl=scripts|limitnum=8|orderby=id desc
 * @param string $info
 * @return array
 */
function parseInfoToArray($info){
	$infos = array();
	parse_str($info,$infos);
	return $infos;
// 	$params=array();
// 	// 去除竖线分隔符两侧的空白符
// 	$info = preg_replace('/\s*\|\s*/','|',trim($info));
// 	$param_array = explode('|',$info);
// 	foreach($param_array as $variable){
// 		if(!empty($variable)){
// 			$expresions = explode('=', $variable);
// 			$key = array_shift($expresions);
// 			$value=implode('=',$expresions);
// 			if($key){
// 				$pos = strpos($key,'[');
// 				if($pos===false){ // 不含[
// 					//$params[$key]=$value;
// 					eval('$params[\''.$key.'\']='.$value.';');
// 				}
// 				else{
// 					if($pos==0) continue; // [不能在第一位
// 					//当含有[ 时，为数组，使用eval来处理赋值语句					
// 					//eval('$'.$key.'='.$value.';');$params[$vkey] = $$vkey;
// 					$vkey = substr($key,0,$pos);
// 					eval('$params[\''.$vkey.'\']='.$value.';');					
// 				}
// 			}
// 		}
// 	}
// 	return $params;
}

/*
 * php5.4 以后，json_encode增加了JSON_UNESCAPED_UNICODE , JSON_PRETTY_PRINT 等几个常量参数。使显示中文与格式化更方便。
 * echo json_encode($arr, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);  
 * 
 */

/** 将数组元素进行urlencode
 * @param String $val
 */
function jsonFormatProtect(&$val){
	if($val!==true && $val!==false && $val!==null){
		$val = urlencode($val);
	}
}
/** Json数据格式化
 * @param  Mixed  $data   数据
 * @param  String $indent 缩进字符，默认4个空格
 * @return JSON
 */
function jsonFormat($data, $indent=null){
    
    if( is_array($data) && defined('JSON_UNESCAPED_UNICODE') && defined('JSON_PRETTY_PRINT') ) {
        return json_encode($data, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
    }
    if(is_array($data)) {
        // 对数组中每个元素递归进行urlencode操作，保护中文字符
        array_walk_recursive($data, 'jsonFormatProtect');
        // json encode
        $data = json_encode($data);
    }

	// 将urlencode的内容进行urldecode
	$data = urldecode($data);

	// 缩进处理
	$ret = '';
	$pos = 0;
	$length = strlen($data);
	$indent = isset($indent)? $indent : '    ';
	$newline = "\n";
	$prevchar = '';
	$outofquotes = true;

	for($i=0; $i<=$length; $i++){

		$char = substr($data, $i, 1);

		if($char=='"' && $prevchar!='\\'){
			$outofquotes = !$outofquotes;
		}elseif(($char=='}' || $char==']') && $outofquotes){
			$ret .= $newline;
			$pos --;
			for($j=0; $j<$pos; $j++){
				$ret .= $indent;
			}
		}

		$ret .= $char;

		if(($char==',' || $char=='{' || $char=='[') && $outofquotes){
			$ret .= $newline;
			if($char=='{' || $char=='['){
				$pos ++;
			}

			for($j=0; $j<$pos; $j++){
				$ret .= $indent;
			}
		}

		$prevchar = $char;
	}

	return $ret;
}

function arrayToJson($val) {
    App::uses("Services_JSON", "Pear");
    $json = new Services_JSON();
    return $json->encode($val);
}

function jsonToArray($val) {
    App::uses("Services_JSON", "Pear");
    $json = new Services_JSON();
    $obj = $json->decode($val);
    return object_to_array($obj);
}
/**
 * 修改数组的所有索引为小写
 * @param unknown_type $array
 * @return multitype:NULL unknown
 */
function array_change_keylower($array) {
    $temparray = array();
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $temparray[strtolower($key)] = array_change_keylower($value);
        } else {
            $temparray[strtolower($key)] = $value;
        }
    }
    return $temparray;
}

function mkdir_p($dir, $mode = 0777)  {
	if (is_dir($dir) || @mkdir($dir, $mode)) return TRUE;
	if (!mkdir_p(dirname($dir), $mode)) return FALSE;
	return @mkdir($dir, $mode);
}

/**
 * substr 对字符截取，英文字符两个占一个长度，汉字一个占一个长度
 * @param $string
 * @param $length
 * @param $strpad
 */
function gsubstr($string, $length, $strpad='') {
    if (strlen($string) > $length) {
        for ($i = 0; $i < $length; $i++)
            if (ord($string[$i]) > 128) {
                $i++;
            }
        if ($i > $length) {
            $i -= 2;
        }
        $string = substr($string, 0, $i) . $strpad;
    }
    return $string;
}

function filterEmoji($str)
{
    //遍历字符串中的每个字符，如果该字符的长度为4个字节，就将其删除
    $str = preg_replace_callback(
        '/./u',
        function (array $match) {
            return strlen($match[0]) >= 4 ? '' : $match[0];
        },
        $str);

    return $str;
}

/**
 * 主要用于HtmlParsers::parse,一键排版计算与判断标题字数。
 * @param $str 计算长度字符串
 * @return float 返回字数
 */
function ustrlen($str) {
    $count = 0.0;
    for ($i = 0; $i < strlen($str); $i++) {        
        $value = ord($str[$i]);
        if ($value > 127) {
            if ($value >= 192 && $value <= 223) {
                $i++;
            } else if ($value >= 224 && $value <= 239) {
                $i = $i + 2;
            } else if ($value >= 240 && $value <= 247) {
                $i = $i + 3;
            } else if ($value >= 248 && $value <= 251) {
                $i = $i + 4;
            } else if ($value >= 252 && $value <= 253) {
                $i = $i + 5;
            } else {                
                //die('Not a UTF-8 compatible string');
            }
            $count++;
        } else {
        	if($value == 32) {
        		$count ++;  //空格占一个长度
        	}
        	else{
        		$count = $count + 0.33;  //英文字符三个占一个长度，汉字一个占一个长度
        	}
            
        }
    }    
    return round($count);
}


function usubstr($str, $position, $length=0, $strpad='') {
    $start_byte = 0;
    $totallenth = $start_position = $end_position = strlen($str);
    $count = 0.0;
    for ($i = 0; $i < strlen($str); $i++) {
        if ($count >= $position && $start_position > $i) {
            $start_position = $i;
            $start_byte = $count;
        }
        if ( $length && ($count - $position) >= $length ) {
            $end_position = $i;
            break;
        }
        $value = ord($str[$i]);
        if ($value > 127) {
            if ($value >= 192 && $value <= 223) {
                $i++;
            } else if ($value >= 224 && $value <= 239) {
                $i = $i + 2;
            } else if ($value >= 240 && $value <= 247) {
                $i = $i + 3;
            } else if ($value >= 248 && $value <= 251) {
                $i = $i + 4;
            } else if ($value >= 252 && $value <= 253) {
                $i = $i + 5;
            } else {
                $start_position++;
                //die('Not a UTF-8 compatible string');
            }
            $count++;
        } else {
            $count = $count + 0.5;  //英文字符两个占一个长度，汉字一个占一个长度
        }
    }
    $returnstr = substr($str, $start_position, $end_position - $start_position);

    if ($totallenth > $end_position)
        $returnstr.=$strpad;
    return $returnstr;
}

function filterUtf8($str)  
{  
    /*utf8 编码表： 
    * Unicode符号范围           | UTF-8编码方式 
    * u0000 0000 - u0000 007F   | 0xxxxxxx 
    * u0000 0080 - u0000 07FF   | 110xxxxx 10xxxxxx 
    * u0000 0800 - u0000 FFFF   | 1110xxxx 10xxxxxx 10xxxxxx 
    * 
    */  
    $re = '';  
    $str = str_split(bin2hex($str), 2);  

    $mo =  1<<7;  
    $mo2 = $mo | (1 << 6);  
    $mo3 = $mo2 | (1 << 5);         //三个字节  
    $mo4 = $mo3 | (1 << 4);          //四个字节  
    $mo5 = $mo4 | (1 << 3);          //五个字节  
    $mo6 = $mo5 | (1 << 2);          //六个字节  


    for ($i = 0; $i < count($str); $i++)  
    {  
        if ((hexdec($str[$i]) & ($mo)) == 0)  
        {  
            $re .=  chr(hexdec($str[$i]));  
            continue;  
        }  

        //4字节 及其以上舍去  
        if ((hexdec($str[$i]) & ($mo6) )  == $mo6)  
        {  
            $i = $i +5;  
            continue;  
        }  

        if ((hexdec($str[$i]) & ($mo5) )  == $mo5)  
        {  
            $i = $i +4;  
            continue;  
        }  

        if ((hexdec($str[$i]) & ($mo4) )  == $mo4)  
        {  
            $i = $i +3;  
            continue;  
        }  

        if ((hexdec($str[$i]) & ($mo3) )  == $mo3 )  
        {  
            $i = $i +2;  
            if (((hexdec($str[$i]) & ($mo) )  == $mo) &&  ((hexdec($str[$i - 1]) & ($mo) )  == $mo)  )  
            {  
                $r = chr(hexdec($str[$i - 2])).  
                    chr(hexdec($str[$i - 1])).  
                    chr(hexdec($str[$i]));  
                $re .= $r;  
            }  
            continue;  
        }  



        if ((hexdec($str[$i]) & ($mo2) )  == $mo2 )  
        {  
            $i = $i +1;  
            if ((hexdec($str[$i]) & ($mo) )  == $mo)  
            {  
                $re .= chr(hexdec($str[$i - 1])) . chr(hexdec($str[$i]));  
            }  
            continue;  
        }  
    }  
    return $re;  
}  

/**
 * XML字符串转数组
 *
 * @param string $string	XML字符串
 */
function xml_to_array($string) {
    if (empty($string))
        return array();
    //App::import('Lib', 'Xml');
    require_once CORE_PATH . 'Cake/Utility/Xml.php';
    // cake 2.0
    $xml = Xml::build($string);
    $xmlarray = Xml::toArray($xml);
    //print_r($string); print_r($xmlarray);exit;
    //$xml = Xml::build($string);
    //$xmlarray=array();
    //$xmlarray['options'] = simplexml2array($xml);
//	$xmlarray = array_change_keylower($xmlarray,CASE_LOWER);
    return $xmlarray;
}

/**
 * 数组转XML
 * @param string $data	XML文件、URL或字符串
 * @param bool $isfile	data类型是XML文件、URL还是字符串
 * @param string $is_iconv	转码格式，默认为空不进行转码，格式如 'utf-8|gbk' 为把数据由 utf-8 转码为 gbk
 */
function array_to_xml($data, $options =array()) {
    /**
     * use this to convert array  in cake 1.3.x
     */
    //require_once CORE_PATH.'Cake/Utility/Xml.php';
    App::uses('Xml', 'Utility');
    //print_r($data);print_r($options);exit;
    if (count($data) > 1) {
        $t_array = array();
        $t_array['xml'] = $data;
        $data = $t_array;
    }
    $options += array('format' => 'tags');
    $xml = Xml::build($data, $options);
    if(method_exists($xml,'asXML')) {
    	return $xml->asXML();
    }
    elseif(method_exists($xml,'saveXML')){
    	return $xml->saveXML();
    }
    else{
    	return null;
    }
}

/**
 * 类、对象转数组
 *
 * @param object $object	类、对象
 * @param string $is_iconv	转码格式，默认为空不进行转码，格式如 'utf-8|gbk' 为把数据由 utf-8 转码为 gbk
 */
function object_to_array($object, $is_iconv = '') {
    $array = array();
    if (is_object($object)) {
        $object = get_object_vars($object);
    }
    if (is_array($object)) {
        foreach ($object as $key => $val) {
            $array[$key] = object_to_array($val, $is_iconv);
        }
    } else {
        $array = $object;
        if (!empty($is_iconv)) {
            $is_iconv = explode('|', $is_iconv);
            $array = @iconv($is_iconv[0], $is_iconv[1], $array);
        }
    }
    unset($object);
    return $array;
}

/**
 * 删除数组中为某一值的所有元素,不传value时，删除空值
 * @param $array
 * @param $value
 */
function array_delete_value($array, $value=null,$trim = false) {
    if (!empty($array) && is_array($array)) {
        foreach ($array as $k => $v) {
            if($trim && $v == trim($value)){
            	unset($array[$k]);
            }
            elseif ($v == $value) {
                unset($array[$k]);
            }
        }
    } else {
        $array = array();
    }
    return $array;
}

function array_to_table($array,$skip_empty = true){
	if(!is_array($array) || empty($array)){
		return '';
	}
	$HTML = "<table class=\"table\" width=\"100%\" border=\"1\" cellpadding=\"0\" cellspacing=\"0\" bordercolor=\"#CCC\">"; 
	foreach($array as $key=> $value){
		if(empty($value) && $skip_empty){
			continue;
		}
		if(is_array($value)){
			$HTML .= "<tr><td>$key</td><td class=\"make_table_td\">".array_to_table($value)."</td></tr>";
		}
		else{
			$HTML .= "<tr><td>$key</td><td class=\"make_table_td\">".nl2br($value)."</td></tr>";
		} 
	}
	$HTML .= "</table>"; 
	return $HTML;
}

/**
 * 对数组的各项key,value递归进行rawurlencode，并返回数组.key,value同时处理
 * @param $array
 * @return array
 */
function array_rawurlencode($array) {
    if (is_array($array)) {
        foreach ($array as $key => $val) {
            if (is_array($val)) {
                $newkey = rawurlencode($key);
                $array[$newkey] = array_rawurlencode($val);
                if ($newkey != $key) {
                    unset($array[$key]);
                }
            } else {
                $newkey = rawurlencode($key);
                $array[$newkey] = rawurlencode($val);
                if ($newkey != $key) {
                    unset($array[$key]);
                }
            }
        }
        return $array;
    } else {
        return rawurlencode($array);
    }
}
function array_strip_tags($array,$trim=true){
	if (is_array($array)) {
		foreach ($array as $key => &$val) {
			if (is_array($val)) {
				$val = array_strip_tags($val);
			} else {
				if($trim){
					$val = trim(strip_tags($val));
				}
				else{
					$val = strip_tags($val);
				}				
			}
		}
		return $array;
	} else {
		if($trim){
			return trim(strip_tags($array));
		}
		else{
			return strip_tags($array);
		}
	}
}

/**
 * mime_content_type函数已不建议使用，定义get_mime_type函数获取文件的mime类型。
 * 获取mime的函数环境很可能不支持，默认使用文件后缀对应类型的方法来匹配，不存在的类型再用函数获取。
 */
function get_mime_type($filename) {

	$mime_types = array(
			'txt' => 'text/plain',
			'htm' => 'text/html',
			'html' => 'text/html',
			'php' => 'text/html',
			'css' => 'text/css',
			'js' => 'application/javascript',
			'json' => 'application/json',
			'xml' => 'application/xml',
			'swf' => 'application/x-shockwave-flash',
			'flv' => 'video/x-flv',
			// images
			'png' => 'image/png',
			'jpe' => 'image/jpeg',
			'jpeg' => 'image/jpeg',
			'jpg' => 'image/jpeg',
			'gif' => 'image/gif',
			'bmp' => 'image/bmp',
			'ico' => 'image/vnd.microsoft.icon',
			'tiff' => 'image/tiff',
			'tif' => 'image/tiff',
			'svg' => 'image/svg+xml',
			'svgz' => 'image/svg+xml',
			'ief' => 'image/ief',
			'djvu' => 'image/vnd.djvu',
			'djv' => 'image/vnd.djvu',
			'wbmp' => 'image/vnd.wap.wbmp',
			'ras' => 'image/x-cmu-raster',
			'pnm' => 'image/x-portable-anymap',
			'pbm' => 'image/x-portable-bitmap',
			'pgm' => 'image/x-portable-graymap',
			'ppm' => 'image/x-portable-pixmap',
			'rgb' => 'image/x-rgb',
			'xbm' => 'image/x-xbitmap',
			'xpm' => 'image/x-xpixmap',
			'xwd' => 'image/x-windowdump',
			// archives
			'zip' => 'application/zip',
			'rar' => 'application/x-rar-compressed',
			'exe' => 'application/x-msdownload',
			'msi' => 'application/x-msdownload',
			'cab' => 'application/vnd.ms-cab-compressed',
			// audio/video
			'mp3' => 'audio/mpeg',
			'qt' => 'video/quicktime',
			'mov' => 'video/quicktime',
			'mpeg' => 'video/mpeg',
			'mpg' => 'video/mpeg',
			'mpe' => 'video/mpeg',
			'mxu' => 'video/vnd.mpegurl',
			'avi' => 'video/x-msvideo',
			'movie' => 'video/x-sgi-movie',
			'au' => 'audio/basic',
			'snd' => 'audio/basic',
			'mid' => 'audio/midi',
			'midi' => 'audio/midi',
			'kar' => 'audio/midi',
			'mpga' => 'audio/mpeg',
			'mp2' => 'audio/mpeg',
			'aif' => 'audio/x-aiff',
			'aiff' => 'audio/x-aiff',
			'aifc' => 'audio/x-aiff',
			'm3u' => 'audio/x-mpegurl',
			'ram' => 'audio/x-pn-realaudio',
			'rm' => 'audio/x-pn-realaudio',
			'rpm' => 'audio/x-pn-realaudio-plugin',
			'ra' => 'audio/x-realaudio',
			'wav' => 'audio/x-wav',
			// adobe
			'pdf' => 'application/pdf',
			'psd' => 'image/vnd.adobe.photoshop',
			'ai' => 'application/postscript',
			'eps' => 'application/postscript',
			'ps' => 'application/postscript',
			// ms office
			'doc' => 'application/msword',
			'rtf' => 'application/rtf',
			'xls' => 'application/vnd.ms-excel',
			'ppt' => 'application/vnd.ms-powerpoint',
			// open office
			'odt' => 'application/vnd.oasis.opendocument.text',
			'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
	);

	$ext = strtolower(end(explode('.', $filename)));
	if (array_key_exists($ext, $mime_types)) {
		return $mime_types[$ext];
	}
	else {
		$img_file = new File($filename, true);
		$mime = $img_file->mime();
        $img_file->close();
        if($mime==false && function_exists('exif_imagetype')){
			$exif_type = @exif_imagetype($filename);
			if($exif_type==IMAGETYPE_GIF){
				$mime = 'image/gif';
			}
			elseif($exif_type==IMAGETYPE_JPEG){
				$mime = 'image/jpeg';
			}
			elseif($exif_type==IMAGETYPE_PNG){
				$mime = 'image/png';
			}
			elseif($exif_type==IMAGETYPE_BMP){
				$mime = 'image/bmp';
			}
		}
		if($mime!=false){
			return $mime;
		}
		else{
			return 'application/octet-stream';
		}
	}
}

function replaceLazyLoad($matches){
    if( empty($matches[2]) ) {
        return null;
    }
    if(! is_array($GLOBALS['lazy_images']) ) {
        $GLOBALS['lazy_images'] = array();
    }
    array_push($GLOBALS['lazy_images'],$matches[2]);
    if(count($GLOBALS['lazy_images'])==1 && !defined('LAZY_ALL_IMAGE') ){ //默认保留第一张图片不处理
        return $matches[0];
    }
    else{
        $attrs = $matches[1].' '.$matches[3];
        // 去掉原有的图片的class样式
        if(strpos($attrs,'class=') !== false) {
            $attrs = preg_replace('/class=[\'|"].+?["|\']/i','',$attrs);
        }
        return '<img '.$attrs.' class="lazy" src="http://static.135editor.com/img/grey.gif" data-src="'.$matches[2].'"/>';
    }
}

function strip_imgthumb_opr($imgurl){ //过滤阿里云等图片处理参数
	$idx = strpos($imgurl,'@');
	if($idx > 0) {
		return substr($imgurl,0,$idx); // 返回从start到end的位置，不包含end的那个字母
	}
	else{
        $idx = strpos($imgurl,'?');
        if($idx > 0) {
            return substr($imgurl,0,$idx);
        }
    }
	return $imgurl;
}

function  lazyloadimg($content) {
    $GLOBALS['lazy_images'] = array();

    if(strpos($content,'<img') === false){
        return $content;
    }
    
    //$template = preg_replace_callback('/{{varhtml (.+?)}}/is',array($this,'varhtml'),$template);
    //<img border="1" alt="" id="vimage_3462857" src="/files/remote/2010-10/cnbeta_2038145814065004.jpg" />
    // 双引号，单引号，无引号三种图片类型的代码。
    // <img  ... class="wp-image-89398 aligncenter" ...>
    // 去掉原有的图片的class样式
    //$content = preg_replace('/<img([^>]+?)class=[\'|"].+?["|\']([^>]+?)>/is','<img \\1 \\2>',$content);
    // $content = preg_replace('/<img([^>]+?)src="([^"]*?)"([^>]*?)>/is', "<img \\1src=\"" . Router::url('/img/grey.gif') . "\" class=\"lazy\" data-original=\"\\2\" \\3>", $content);

    // $content = preg_replace('/<img([^>]+?)src=\'([^\']+?)\'([^>]+?)>/is', "<img \\1src=\"" . Router::url('/img/grey.gif') . "\" class=\"lazy\" data-original=\"\\2\" \\3>", $content);
    // //[^\s"\'] 表示非空、非引号同时成立
    // $content = preg_replace('/<img([^>]+?)src=([^\s"\']+?)([^>]+?)>/is', "<img \\1src=\"" . Router::url('/img/grey.gif') . "\" class=\"lazy\" data-original=\"\\2\" \\3>", $content);

    //带双引号,单引号的
    $content = preg_replace_callback('/<img([^>]+?)src=["|\']([^"]*?)["|\']([^>]*?)\/?\s*>/is','replaceLazyLoad', $content);
    //带单引号的
    //$content = preg_replace_callback('/<img([^>]+?)src=\'([^\']+?)\'([^>]+?)>/is', array($this,'_replaceLazyLoad'), $content);
    //[^\s"\'] 表示非空、非引号同时成立，不带引号的。不带引号的暂不处理，符合条件的内容少，多匹配一次降低性能，没必要要求这么严格
    //$content = preg_replace_callback('/<img([^>]+?)src=([^\s"\']+?)([^>]+?)>/is',array($this,'_replaceLazyLoad'), $content);

   	// echo $content;exit;
    return $content;
}

/**
 * 判断一个ip是否是内网IP
 * @param unknown_type $ip
 * @return boolean
 */
function is_inner_ip($ip) {
    $segs = explode('.', $ip);
    if ($segs[0] == '10' || ($segs[0] == '172' && $segs[1] >= 16 && $segs[1] <= 31) || ($segs[0] == '192' && $segs[1] == '168')) {
        return true;
    } else {
        return false;
    }
}

/**
 * 
 * 获取客户端的IP
 */
function get_remote_ip() {
    $ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : getenv('HTTP_CLIENT_IP');
    if ($ip)
        return $ip;
    $http_x_forwarded_for = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : getenv('HTTP_X_FORWARDED_FOR');
    if ($http_x_forwarded_for) {
        $forward_ip_list = preg_split('/,\s*/', $http_x_forwarded_for);
        foreach ($forward_ip_list as $ip) {
            if (!is_inner_ip($ip)) {
                return $ip;
            }
        }
    }
    $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : getenv('REMOTE_ADDR');
    if ($ip && $ip != 'unknown')
        return $ip;

    if (!empty($forward_ip_list)) {
        return $forward_ip_list[0];
    }
    return 'unknown';
}





function get_time_process($start_date,$end_date,$cur_date= ''){

	$start_time = strtotime($start_date);
	$end_time = strtotime($end_date);

	if($cur_date){
		$cur_time = strtotime($cur_date);
	}
	else{
		$cur_time = time();
	}
	if($start_time > $cur_time || $end_time <= $start_time ){
		return 0;
	}

	$total_days = ($end_time - $start_time )/86400;

	$pass_days = ceil($cur_time - $start_time)/86400;
	if($pass_days > $total_days){
		$pass_days = $total_days;
	}

	return intval($pass_days*100/$total_days);
}

function getAvatarPath($uid){
	return DS.($uid/1000%1000).DS.($uid%1000).DS;
}
function getAvatarUrl($uid){
	return UPLOAD_FILE_URL.UPLOAD_RELATIVE_PATH.'avatar/'.($uid/1000%1000).'/'.($uid%1000).'/'.$uid.'_0.jpg';
}

function getHumanFileSize($size){
	if($size > 1024*1024){
		$file_size = round($size/1024/1024,0,2).'MB';
	}
	elseif($size > 1024){
		$file_size = round($size/1024,0,2).'KB';
	}
	else{
		$file_size = $size.'B';
	}
	return $file_size;
}

function get_time_left($start_date,$end_date,$cur_date= ''){

	$start_time = strtotime($start_date);
	$end_time = strtotime($end_date);

	if($cur_date){
		$cur_time = strtotime($cur_date);
	}
	else{
		$cur_time = time();
	}

	$total_days = ($end_time - $start_time )/86400;

	if($start_time > $cur_time){
		// 没有开始,100%的剩余时间
		return array('days'=> $total_days,'percent'=> 100 );
	}
	elseif($end_time <= $cur_time){ //已结束
		return array('days'=> 0,'percent'=>0 );
	}

	$left_days = ($end_time - $cur_time )/86400;

	return array('days'=> ceil($left_days),'percent'=> intval($left_days*100/$total_days) );
}